<template>
  <div>
    <h3>这是provide组件</h3>
    <button @click="changeColor">改变color</button>
    <a-com></a-com>
  </div>
</template>

<script>
import A from './A.vue';
// import Vue from 'vue';
export default {
  data() {
    return {
      color: 'blue'
    };
  },
  components: {
    'a-com': A
  },
  // 参考文档：https://www.cnblogs.com/goloving/p/13941709.html
  // 1.provide/inject成对出现，应用场景；是跨级通信provide对象或者provide方法提供变量值，inject:['变量名']引入。是对prop:['']
  // 父组件向子组件传值的补充
  // 2.官网地址：https://cn.vuejs.org/v2/guide/components-edge-cases.html#%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5
  // 3.这种方式的优点（可以理解为扩展版的props）：
  // 3.1 父组件不需要知道哪些子组件会引用这个property
  // 3.2 子组件也不需要知道property来自那个父组件
  // 4.这种方式的缺点
  // 4.1 父组件提供的property是非响应式的，这是出于设计的考虑，用来创建一个中心化规模化的数据
  // provide: { color: 'green' },
  // provide: { color: { key: 'green' } }, // color是一个对象，inject['color']是拿不到数据的
  // 4.2函数方式-推荐这种方式
  // provide() {
  //   return { color: 'blue' };
  // }
  /* provide也有两种书写方式：
  1.对象方式
  不建议使用provide:{color:'blue'}这种书写方式，原因是：color如果是对象，inject['color']是拿不到值的
  2.函数方式
  provide(){
    this.theme=Vue.observable({
      color:this.color
    });
    return {theme:this.theme};
  }
  */

  // vue2.6 版本以后，响应式的方式（仍然推荐方式二）
  // 方式一 提供祖先组件的实例
  // provide() {
  //   return {
  //     theme: this // 方法一：提供祖先组件的实例，这种方式是响应式的
  //   };
  // },
  // methods: {
  // provide() {
  //   return {
  //     theme: this// 这种方式是响应式的，但是缺点是：这种方式会在实例上挂载许许多多不必要的属性，比如挂载下面的this.color
  //   };
  // },
  // provide() {
  //   //  返回一个theme对象数据，改用vue 2.6最新的API,Vue.observable({})下面的方式，可以实现响应式了
  //   // 测试Vue.observable方式，没有实现响应式
  //   this.theme = Vue.observable({
  //     color: this.color
  //   });
  //   return { theme: this.theme };
  // },
  provide() {
    return {
      theme: {
        // color要想实现响应式：
        // 两步：1.将color值放在一个函数中，作为返回值；2.在inject接收的组件中，使用computed进行侦听
        reactiveData: state => (state = this.color)
      }
    };
  },
  methods: {
    // 对应响应式方式一，直接返回实例来实现响应式 return {theme:this};这种方式会使得实例上挂载了许多不必要的东西
    // changeColor(color) {
    //   this.color = color === 'blue' ? 'red' : 'blue';
    // }
    // 对应响应式方式二，引入Vue.observable({})方法来实现响应式
    changeColor() {
      this.color = 'red';
    }
  }
};
</script>

<style scoped></style>
